package com.fdb.smcts.core.util;

import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fdb.smcts.core.exception.BizException;

public class MessageRuleCheckUtil {
	private static Logger logger = LoggerFactory.getLogger(MessageRuleCheckUtil.class);

	// yyyyMMddHHmmss格式时间正则表达式
	private static final String REGEX_YYYYMMDDHHMMSS = "((([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})(((0[13578]|1[02])(0[1-9]|[12][0-9]|3[01]))|" + 
			"((0[469]|11)(0[1-9]|[12][0-9]|30))|(02(0[1-9]|[1][0-9]|2[0-8]))))|((([0-9]{2})(0[48]|[2468][048]|[13579][26])|" + 
			"((0[48]|[2468][048]|[3579][26])00))0229))" + 
			"([0-1][0-9]|2[0-3])([0-5][0-9])([0-5][0-9])$";

	/**
	 * 
	 * <p>
	 * <h2>数值类型校验</h2>
	 * 		<ol>请添加简述</ol>
	 * <h2>功能描述</h2>
	 * 		<ol>请添加功能详细的描述</ol>
	 * </p>
	 * @param param
	 * @param name
	 * @throws BizException
	 */
	public static void checkDouble(String param, String name) throws BizException {
		if (!NumberUtility.isDouble(param)) {
			logger.error("参数["+ name +"], 值["+ param +"]合规性校验不通过!");
			throw new BizException("参数["+ name +"], 值["+ param +"]合规性校验不通过!");
		}
	}
	
	/**
	 * <p>
	 * <h2>数值类型校验</h2>
	 * 		<ol>请添加简述</ol>
	 * <h2>功能描述</h2>
	 * 		<ol>该方法提供自定义错误码返回，用于管理异常类型</ol>
	 * </p>
	 * @param param 需要检验的参数
	 * @param name 参数的中文名
	 * @param errorCode 校验错误返回代码
	 * @author  qiuyf
	 * @since 2019年3月8日 上午9:23:30
	 * @version 0.1 初始为0.1,后续变更则修改
	 */
	public static void checkDouble(String param, String name, String errorCode) throws BizException {
		if (!NumberUtility.isDouble(param)) {
			logger.error("参数["+ name +"], 值["+ param +"]合规性校验不通过!");
			throw new BizException(errorCode, "参数["+ name +"], 值["+ param +"]合规性校验不通过!");
		}
	}
	
	/**
	 * 
	 * <p>
	 * <h2>整数类型校验</h2>
	 * 		<ol>请添加简述</ol>
	 * <h2>功能描述</h2>
	 * 		<ol>请添加功能详细的描述</ol>
	 * </p>
	 * @param param
	 * @param name
	 * @throws BizException
	 */
	public static void checkInteger(String param, String name) throws BizException {
		if (!NumberUtility.isInteger(param)) {
			logger.error("参数["+ name +"], 值["+ param +"]合规性校验不通过!");
			throw new BizException("参数["+ name +"], 值["+ param +"]合规性校验不通过!");
		}
	}
	
	/**
	 * 
	 * <p>
	 * <h2>数字校验</h2>
	 * 		<ol>请添加简述</ol>
	 * <h2>功能描述</h2>
	 * 		<ol>请添加功能详细的描述</ol>
	 * </p>
	 * @param param
	 * @param name
	 * @throws BizException
	 */
	public static void checkNumeric(String param, String name) throws BizException {
		if (!NumberUtility.isNumeric(param)) {
			logger.error("参数["+ name +"], 值["+ param +"]合规性校验不通过!");
			throw new BizException("参数["+ name +"], 值["+ param +"]合规性校验不通过!");
		}
	}
	
		/**
	 * <p>
	 * <h2>整数类型校验</h2>
	 * 		<ol>请添加简述</ol>
	 * <h2>功能描述</h2>
	 * 		<ol>该方法提供自定义错误码返回，用于管理异常类型</ol>
	 * </p>
	 * @param param 需要检验的参数
	 * @param name 参数的中文名
	 * @param errorCode 校验错误返回代码
	 * @author  qiuyf
	 * @since 2019年3月8日 上午9:27:09
	 * @version 0.1 初始为0.1,后续变更则修改
	 */
	public static void checkInteger(String param, String name, String errorCode) throws BizException {
		if (!NumberUtility.isInteger(param)) {
			logger.error("参数["+ name +"], 值["+ param +"]合规性校验不通过!");
			throw new BizException(errorCode, "参数["+ name +"], 值["+ param +"]合规性校验不通过!");
		}
	}   
	
	/**
	 * 拼音校验
	 * <p>
	 * <h2>简述</h2>
	 * 		<ol>请添加简述</ol>
	 * <h2>功能描述</h2>
	 * 		<ol>请添加功能详细的描述</ol>
	 * </p>
	 * @param param
	 * @throws BizException
	 */
	public static void checkNameSpell(String param) throws BizException {
		Matcher matcher = Pattern.compile("([ ]||[a-zA-Z])+").matcher(param);
		if (!matcher.matches()) {
			logger.error("拼音["+ param +"]合规性校验不通过!");
			throw new BizException("拼音["+ param +"]合规性校验不通过!");
		}
	}
	
	/**
	 * 
	 * <p>
	 * <h2>身份证合规性校验</h2>
	 * 		<ol>该方法只支持18为身份证校验</ol>
	 * <h2>功能描述</h2>
	 * 		<ol>请添加功能详细的描述</ol>
	 * </p>
	 * @param idNo
	 * @throws BizException
	 */
	public static void validateIdNo18(String idNo) throws BizException {
		if (idNo.length() != 18) {
			throw new BizException("只支持18位身份证校验");
		}
		
		String[] valCodeArr = {"1", "0", "x", "9", "8", "7", "6", "5", "4", "3", "2"};
		String[] wi = {"7", "9", "10", "5", "8", "4", "2", "1", "6", "3", "7", "9", "10", "5", "8", "4", "2"};
		String ai = ""; //除最后一位以外的所有对象数值
		String idCard = idNo.toLowerCase();
		
		if (idCard.length() == 18) {
			ai = idCard.substring(0, 17);
		} else if (idCard.length() == 15) {
			ai = idCard.substring(0, 6) +"19"+ idCard.substring(6, 15);
		}
		
		if (!NumberUtility.isNumeric(ai)) {
			throw new BizException( "18位证件号码除最后一位外均为数字");
		}
		
		String year = ai.substring(6, 10);
		String month = ai.substring(10, 12);
		String day = ai.substring(12, 14);
		
		GregorianCalendar gc = new GregorianCalendar();
		
		try {
			if ((gc.get(Calendar.YEAR) - Integer.parseInt(year)) > 150 || 
				(gc.getTime().getTime() - DateUtility.parseDate(year+"-"+month+"-"+day, "yyyy-MM-dd").getTime()) < 0) {
				throw new BizException("出生日期不在有效范围内");
			}
		} catch (BizException e) {
			throw e;
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			throw new BizException(e.getMessage());
		}
		
		if (Integer.parseInt(month) > 12 || Integer.parseInt(month) == 0) {
			throw new BizException("身份证月份无效");
		}
		
		if (Integer.parseInt(day) > 31 || Integer.parseInt(day) == 0) {
			throw new BizException("身份证日期无效");
		}
		
		//最后一位校验
		int totalmulAiWi = 0;
		for (int i = 0; i < 17; i++) {
			totalmulAiWi = totalmulAiWi + Integer.parseInt(String.valueOf(ai.charAt(i))) * Integer.parseInt(wi[i]);
		}
		
		int modValue = totalmulAiWi % 11;
		String strVerifyCode = valCodeArr[modValue];
		ai = ai + strVerifyCode;
		
		if (!ai.equals(idCard)) {
			throw new BizException("身份证无效, 不是合法身份证号码");
		}
		
	}
	
	/**
	 * <p>
	 * <h2>身份证合规性校验</h2>
	 * 		<ol>该方法只支持18为身份证校验</ol>
	 * <h2>功能描述</h2>
	 * 		<ol>该方法提供自定义错误码返回，用于管理异常类型</ol>
	 * </p>
	 * @param idNo 身份证号码
	 * @param errorCode 校验报错需要返回的错误代码
	 * @author  qiuyf
	 * @since 2019年3月8日 上午9:08:10
	 * @version 0.1 初始为0.1,后续变更则修改
	 */
	public static void validateIdNo18(String idNo, String errorCode) throws BizException {
		if (idNo.length() != 18) {
			throw new BizException(errorCode, "只支持18位身份证校验");
		}
		String[] valCodeArr = {"1", "0", "x", "9", "8", "7", "6", "5", "4", "3", "2"};
		String[] wi = {"7", "9", "10", "5", "8", "4", "2", "1", "6", "3", "7", "9", "10", "5", "8", "4", "2"};
		String ai = ""; //除最后一位以外的所有对象数值
		String idCard = idNo.toLowerCase();
		
		if (idCard.length() == 18) {
			ai = idCard.substring(0, 17);
		} else if (idCard.length() == 15) {
			ai = idCard.substring(0, 6) +"19"+ idCard.substring(6, 15);
		}
		
		if (!NumberUtility.isNumeric(ai)) {
			throw new BizException(errorCode, "18位证件号码除最后一位外均为数字");
		}
		
		String year = ai.substring(6, 10);
		String month = ai.substring(10, 12);
		String day = ai.substring(12, 14);
		
		GregorianCalendar gc = new GregorianCalendar();
		
		try {
			if ((gc.get(Calendar.YEAR) - Integer.parseInt(year)) > 150 || 
				(gc.getTime().getTime() - DateUtility.parseDate(year+"-"+month+"-"+day, "yyyy-MM-dd").getTime()) < 0) {
				throw new BizException(errorCode, "出生日期不在有效范围内");
			}
		} catch (BizException e) {
			throw e;
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			throw new BizException(errorCode, e.getMessage());
		}
		
		if (Integer.parseInt(month) > 12 || Integer.parseInt(month) == 0) {
			throw new BizException(errorCode, "身份证月份无效");
		}
		
		if (Integer.parseInt(day) > 31 || Integer.parseInt(day) == 0) {
			throw new BizException(errorCode, "身份证日期无效");
		}
		
		//最后一位校验
		int totalmulAiWi = 0;
		for (int i = 0; i < 17; i++) {
			totalmulAiWi = totalmulAiWi + Integer.parseInt(String.valueOf(ai.charAt(i))) * Integer.parseInt(wi[i]);
		}
		
		int modValue = totalmulAiWi % 11;
		String strVerifyCode = valCodeArr[modValue];
		ai = ai + strVerifyCode;
		
		if (!ai.equals(idCard)) {
			throw new BizException(errorCode, "身份证无效, 不是合法身份证号码");
		}
	}
	
	
	/**
	 * 
	 * <p>
	 * <h2>简述</h2>
	 * 		<ol>日期检查</ol>
	 * <h2>功能描述</h2>
	 * 		<ol>请添加功能详细的描述</ol>
	 * </p>
	 * @param sName
	 * @param date
	 * @param pattern
	 * @throws BizException
	 */
	public static void checkDate(String sName, String date, String pattern) throws BizException {
		try {
			// DateUtility.checkDate1(date, sName);
			DateUtility.checkDate(date, pattern);
		} catch (Exception e) {
			logger.error("参数["+ sName +"]对应的值["+ date +"], 不符合定义格式["+ pattern +"]!");
			throw new BizException("参数["+ sName +"]对应的值["+ date +"], 不符合定义格式["+ pattern +"]!");
		}
		logger.debug("参数["+ sName +"]对应的值["+ date +"], 格式["+ pattern +"]校验通过!");
	}
	
	/**
	 * <p>
	 * <h2>简述</h2>
	 * 		<ol>日期检查</ol>
	 * <h2>功能描述</h2>
	 * 		<ol>该方法提供自定义错误码返回，用于管理异常类型</ol>
	 * </p>
	 * @param sName
	 * @param date
	 * @param pattern
	 * @param errorCode 校验报错需要返回的错误代码
	 * @author  qiuyf
	 * @since 2019年3月8日 上午9:36:11
	 * @version 0.1 初始为0.1,后续变更则修改
	 */
	public static void checkDate(String sName, String date, String pattern, String errorCode) throws BizException {
		try {
			DateUtility.checkDate(date, pattern);
		} catch (Exception e) {
			logger.error("参数["+ sName +"]对应的值["+ date +"], 不符合定义格式["+ pattern +"]!");
			throw new BizException(errorCode, "参数["+ sName +"]对应的值["+ date +"], 不符合定义格式["+ pattern +"]!");
		}
		logger.debug("参数["+ sName +"]对应的值["+ date +"], 格式["+ pattern +"]校验通过!");
	}

	/**
	 * 需求编号：【2019D0519】（业务提的需求编号）
	 * 问题编号：【xxxxxxx】（若不是因为修复问题而新增该类，则留空）
	 * 开发人员：qiuyf
	 * 创建日期：2019年6月25日 下午5:46:22
	 * 功能描述：yyyyMMddHHmmss格式时间检查
	 */
	public static Matcher checkDate(String dateStr) {
		Pattern pattern = Pattern.compile(REGEX_YYYYMMDDHHMMSS);
		return pattern.matcher(dateStr);
	}


}
